using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;
using Universe.WinForms;
using Universe.WinForms.DropDownUI;

namespace Universe.WinForms.ColorPickerUI
{
    public class ColorPickerButton : Button
    {
        Color _SelectedColor;
        string _SampleCaption;


        public override string Text
        {
            get { return string.Empty; }
            set {  }
        }

        public override ContentAlignment TextAlign
        {
            get { return base.TextAlign; }
            set
            {
                base.TextAlign = value;
            }
        }

        public ColorPickerButton()
        {
            MouseEnter += new EventHandler(OnMouseEnter);
            MouseLeave += new EventHandler(OnMouseLeave);
            MouseUp += new MouseEventHandler(OnMouseUp);
            Paint += new PaintEventHandler(ButtonPaint);
            Click += new EventHandler(ColorPickerButton_Click);
        }

        void ColorPickerButton_Click(object sender, EventArgs e)
        {
            Control owner = this;
            ContentHolder = new DropDownHolder(owner);

            ColorPickerContent content = new ColorPickerContent();
            content.IsSelected = false;
            content.CellNumber = new Size(39,16);
            content.CellSize = new Size(9,9);
            content.SelectedColor = this.SelectedColor;
            content.SelectedColorChanged += new EventHandler(Content_SelectedColorChanged);
            content.Click += new EventHandler(Content_Click);
            content.HandleCreated += new EventHandler(Content_HandleCreated);

            Rectangle rect = owner.Parent.RectangleToScreen(owner.Bounds);
            rect.Y = rect.Bottom + 1;

            int right = rect.Location.X + content.Size.Width;
            if (right > Screen.PrimaryScreen.Bounds.Width)
                ContentHolder.DropDownLocation = new Point(rect.Right - content.Size.Width, rect.Top);
            else
                ContentHolder.DropDownLocation = rect.Location;

            ContentHolder.Controls.Add(content);
            ContentHolder.PopupClose += new DropDownHolderEventHandler(ContentHolder_PopupClose);
            ContentHolder.DropDown();
            // ContentHolder.Controls

        }

        void Content_HandleCreated(object sender, EventArgs e)
        {
            Control c = (Control) sender;
            c.FindForm().KeyPreview = true;
            c.FindForm().KeyPress += new KeyPressEventHandler(PopupForm_KeyPress);
        }

        void PopupForm_KeyPress(object sender, KeyPressEventArgs e)
        {
            // Debug.WriteLine("PopupForm KeyPress: " + (int)e.KeyChar + " (ContentHolder: " + (ContentHolder == null ? null : ContentHolder.GetType().Name));
            if (e.KeyChar == 13)
            {
                if (ContentHolder != null)
                {
                    DropDownHolder h = ContentHolder;
                    ContentHolder = null;
                    h.CloseDropDown();
                }
                e.Handled = true;
            }
        }

        void ContentHolder_PopupClose(object sender, DropDownHolderEventArgs e)
        {
            // Debug.WriteLine("ContentHolder_PopupClose! (" + e.Action +  ", " + e.InputReport +")");
            if (e.InputReport is KeyInputReport && (e.InputReport as KeyInputReport).KeyCode == Keys.Return)
            {
                DropDownHolder h = ContentHolder;
                ContentHolder = null;
                h.CloseDropDown();
            }
        }

        DropDownHolder ContentHolder;

        void Content_Click(object sender, EventArgs e)
        {
            // Debug.WriteLine("Content_Click!");
            if (ContentHolder != null)
            {
                DropDownHolder h = ContentHolder;
                ContentHolder = null;
                h.CloseDropDown();
            }
        }
        
        

        void Content_SelectedColorChanged(object sender, EventArgs e)
        {
            ColorPickerContent c = (ColorPickerContent) sender;
            this.SelectedColor = c.SelectedColor;
        }

        [Category("Color Picker")]
        public Color SelectedColor
        {
            get { return _SelectedColor; }
            set
            {
                if (_SelectedColor != value)
                {
                    _SelectedColor = value;
                    Invalidate();
                }
            }
        }

        void OnMouseEnter(object sender, EventArgs e)
        {
            Invalidate();
        }

        void OnMouseLeave(object sender, EventArgs e)
        {
            Invalidate();
        }

        void OnMouseUp(object sender, MouseEventArgs e)
        {
            Invalidate();
        }

        [Localizable(true)]
        [Category("Color Picker")]
        public string SampleCaption
        {
            get { return _SampleCaption; }
            set
            {
                if (_SampleCaption != value)
                {
                    _SampleCaption = value;
                    Invalidate();
                }
                
            }
        }

        void ButtonPaint(Object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            Rectangle r = ClientRectangle;

            byte border = 4;
            byte right_border = 15;

            Rectangle rc = 
                new Rectangle(
                    r.Left + border, 
                    r.Top + border,
                    r.Width - border - right_border - 1, 
                    r.Height - border*2 - 1);

            SolidBrush centerColorBrush = new SolidBrush(SelectedColor);
            g.FillRectangle(centerColorBrush, rc);
            
            Pen pen = this.Enabled
                ? new Pen(SystemColors.ControlText)
                : new Pen(SystemColors.GrayText);
            
            g.DrawRectangle(pen, rc);

            if (SampleCaption != null && SampleCaption.Trim().Length > 0)
            {
                Rectangle tr = rc;
                int middle = ((int)SelectedColor.R + SelectedColor.G + SelectedColor.B) / 3;
                Color fore = middle >= 128-16 ? Color.Black : Color.White;
                Size sz = g.MeasureString(SampleCaption, SystemFonts.DialogFont).ToSize();

                if (this.TextAlign == ContentAlignment.BottomRight || TextAlign == ContentAlignment.MiddleRight || TextAlign == ContentAlignment.TopRight)
                    tr = new Rectangle(tr.Right - sz.Width - 1 - this.Padding.Right, tr.Top, sz.Width + 1, tr.Height);

                else if (TextAlign == ContentAlignment.BottomCenter || TextAlign == ContentAlignment.MiddleCenter || TextAlign == ContentAlignment.TopCenter)
                    tr = new Rectangle((tr.Left + tr.Right)/2 - sz.Width/2, tr.Top, sz.Width + 1, tr.Height);
                
                else 
                    tr = new Rectangle(tr.Left + this.Padding.Left, tr.Top, tr.Width - Padding.Left, tr.Height);
                    
                g.DrawString(SampleCaption, SystemFonts.DialogFont, new SolidBrush(fore), tr);
                
            }


            //draw the arrow
            Point p1 = new Point(r.Width - 9, r.Height/2 - 1);
            Point p2 = new Point(r.Width - 5, r.Height/2 - 1);
            g.DrawLine(pen, p1, p2);

            p1 = new Point(r.Width - 8, r.Height/2);
            p2 = new Point(r.Width - 6, r.Height/2);
            g.DrawLine(pen, p1, p2);

            p1 = new Point(r.Width - 7, r.Height/2);
            p2 = new Point(r.Width - 7, r.Height/2 + 1);
            g.DrawLine(pen, p1, p2);

            //draw the divider line
            pen = new Pen(SystemColors.ControlDark);
            p1 = new Point(r.Width - 12, 4);
            p2 = new Point(r.Width - 12, r.Height - 5);
            g.DrawLine(pen, p1, p2);

            pen = new Pen(SystemColors.ControlLightLight);
            p1 = new Point(r.Width - 11, 4);
            p2 = new Point(r.Width - 11, r.Height - 5);
            g.DrawLine(pen, p1, p2);
        }
    }
}